import socket
import os
import cv2
import numpy as np
import paho.mqtt.client as mqtt
import random

# 连接服务器
server_ip = '47.119.40.164'
server_port = 39000

# MQTT配置
broker = 'n12ebcd2.ala.cn-hangzhou.emqxsl.cn'
port = 8883
topic = "command"
client_id = f'python-mqtt-{random.randint(0, 1000)}'
username = 'emqx'
password = '123456'

# 使用OpenCV打开摄像头
cap = cv2.VideoCapture(0)  # 0是默认摄像头的ID

if not cap.isOpened():
    print("无法访问摄像头")
    exit()

# 函数：清空摄像头缓存，确保捕获最新图像
def clear_camera_cache():
    for _ in range(5):  # 尝试读取几帧来清空缓存
        cap.read()

# 函数：捕获并上传图片
def capture_and_upload():
    # 清空摄像头缓存
    clear_camera_cache()

    # 每次调用时打开摄像头并读取一帧图像（即拍照）
    ret, frame = cap.read()

    if not ret:
        print("未能成功获取图像")
        return

    # 将图像保存为文件
    image_path = r"photo.jpg"
    cv2.imwrite(image_path, frame)

    # 打开图片并读取为字节流
    with open(image_path, 'rb') as f:
        image_data = f.read()

    # 获取文件名
    filename = os.path.basename(image_path)

    # 发送文件
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect((server_ip, server_port))

        # 发送文件名的长度和文件名
        s.sendall(len(filename).to_bytes(4, byteorder='big'))
        s.sendall(filename.encode('utf-8'))

        # 发送文件大小
        s.sendall(len(image_data).to_bytes(4, byteorder='big'))

        # 发送文件数据
        s.sendall(image_data)

        print(f"Image {filename} uploaded.")

# MQTT回调函数：处理接收到的消息
def on_message(client, userdata, msg):
    try:
        message = msg.payload.decode('utf-8')
        print(f"Received message: {message}")

        # 如果接收到的消息包含action: "capture_snapshot"，执行抓拍
        if '{"action":"capture_snapshot"}' in message:
            print("Capture snapshot command received.")
            capture_and_upload()
    except Exception as e:
        print(f"Error handling message: {e}")

# 设置MQTT客户端
client = mqtt.Client(client_id)
client.username_pw_set(username, password)
client.on_message = on_message

# 连接到MQTT代理
client.tls_set()  # 如果使用SSL/TLS连接
client.connect(broker, port)

# 订阅指令主题
client.subscribe(topic)

# 开始循环接收消息
try:
    print("MQTT client is now listening for commands...")
    client.loop_forever()
except KeyboardInterrupt:
    print("Disconnected from MQTT broker.")
finally:
    cap.release()  # 释放摄像头资源
